﻿using iTool.Cloud.Center.Model;
using iTool.ClusterComponent;
using iTool.Common.Options;
using iToolService.Interfaces;

namespace Limiting.ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {



            string key = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss");

            Console.WriteLine("Hello World!");
            var task = Task.WhenAll(new List<Task> { RunMainAsync() });
            task.Wait();

            // 分布式 > 锁
            // api gateway > {node1,node2}  lock {e - 1}

            // 分布式 > 限流阀
            // api gateway 同一时间 只能处理10个请求，才能保证业务稳定。

            Console.ReadKey();
        }



        /// <summary>
        /// 分布式锁示例
        /// 使用一个工作单元包装一个队列， 当上一个请求完成在继续下一个。 
        /// 防止客户端宕机 导致的大量无效的消息
        /// </summary>
        /// <param name="cluster"></param>
        /// <returns></returns>
        private static async Task LockAsync(iToolClusterHostClient cluster)
        {
            //ILockService lockService = cluster.GetService<ILockService>("product_id1");

            var scopeProvider = new OrderlyWorkScopeProvider("product_id1");


            Parallel.For(1, 20, new ParallelOptions { MaxDegreeOfParallelism = 4 }, async index =>
            {

                using (await scopeProvider.CreateWorkUnitScopeAsync())
                {
                    // logic
                    Console.WriteLine("get lock success:{0},{1}", index, DateTime.Now);
                    await Task.Delay(1000);
                }


                //// 获取锁
                //await lockService.GetLockAsync();

                //Console.WriteLine("get lock success:{0},{1}", index, DateTime.Now);
                //await Task.Delay(1000);
                //// sku --

                //// 释放锁
                //await lockService.FreedLockAsync();
            });

            await Task.CompletedTask; 
        }

        /// <summary>
        /// 分布式函数限流示例
        /// 使用一个工作单元包装一个队列，最多同时等待 限流阀设置的值。
        /// </summary>
        /// <param name="cluster"></param>
        /// <returns></returns>
        private static async Task LimitingAsync(iToolClusterHostClient cluster)
        {

            var scopeProvider = new LimitWorkScopeProvider(3, "test_limit");

            using (await scopeProvider.CreateWorkUnitScopeAsync()) Console.WriteLine("get excuter success - 1");
            await Task.Delay(1000);

            using (await scopeProvider.CreateWorkUnitScopeAsync()) Console.WriteLine("get excuter success - 2");
            using (await scopeProvider.CreateWorkUnitScopeAsync()) Console.WriteLine("get excuter success - 2");
            await Task.Delay(1000);
            using (await scopeProvider.CreateWorkUnitScopeAsync()) Console.WriteLine("get excuter success - 3");
            await Task.Delay(1000);

            using (await scopeProvider.CreateWorkUnitScopeAsync()) Console.WriteLine("get excuter success - 4");
            using (await scopeProvider.CreateWorkUnitScopeAsync()) Console.WriteLine("get excuter success - 4");
            using (await scopeProvider.CreateWorkUnitScopeAsync()) Console.WriteLine("get excuter success - 4");
            await Task.Delay(1000);

            using (await scopeProvider.CreateWorkUnitScopeAsync()) Console.WriteLine("get excuter success - 5");
            await Task.Delay(1000);



            Parallel.For(1, 100, new ParallelOptions { MaxDegreeOfParallelism = 4 }, async index =>
            {
                using (await scopeProvider.CreateWorkUnitScopeAsync())
                {
                    // 获取执行权限
                    //await limitingService.ApplyExcuterAsync();
                    Console.WriteLine("get excuter success:{0},{1}", index, DateTime.Now);
                    await Task.Delay(1000);

                    // 执行完成后释放
                    //await limitingService.FreedOneAsync();
                }
            });

            await Task.CompletedTask;
        }


        /// <summary>
        /// 冥处理
        /// </summary>
        /// <returns></returns>
        private static async Task RequestIdempotenceService(iToolClusterHostClient cluster)
        {
            IRequestIdempotenceService requestIdempotenceService = cluster.GetService<IRequestIdempotenceService>(20, "test_client_token");
            Parallel.For(1, 200, new ParallelOptions { MaxDegreeOfParallelism = 4 }, async index =>
            {
                // 获取执行权限
                if (await requestIdempotenceService.StartIfNotExistAsync("test_request_token" + (index % 10), 10000))
                {
                    Console.WriteLine("get excuter success:{0},{1}", index, DateTime.Now);
                    await Task.Delay(1000);
                    await requestIdempotenceService.SetResultAsync("test_request_token" + (index % 10), DateTime.Now);
                }
                else
                {
                    object value = await requestIdempotenceService.GetResultAsync("test_request_token" + (index % 10));
                    Console.WriteLine("get result value:" + (index % 10) + value.ToString());
                }
            });

            await Task.CompletedTask;
        }

        private static async Task RunMainAsync()
        {
            try
            {
                var builder = new iToolClientBuilder();

                builder.UseAdoNetClustering(new AdoNetClusterOptions
                {
                    AdoNetOptions = new AdoNetOptions
                    {
                        DataSource = "DESKTOP-L0F4SGU",
                        UID = "sa",
                        PWD = "30.3.."
                    },
                    EndpointsOptions = new EndpointsOptions(),
                    ClusterOptions = new ClusterIdentificationOptions(),
                    ResponseTimeout = TimeSpan.FromSeconds(15)
                });

                var cluster = await builder.BuildAndConnectAsync();

                Console.WriteLine("started successfully");

                // 分布式锁示例
                //Console.WriteLine("分布式锁示例 start");
                //await LockAsync(cluster);
                //Console.ReadKey();

                //// 分布式函数限流示例
                Console.WriteLine("函数限流 start");
                await LimitingAsync(cluster);
                Console.ReadKey();

                // 冥处理
                //Console.WriteLine("冥处理 start");
                //await RequestIdempotenceService(cluster);

                Console.ReadKey();


            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
    }
}
